package org.example.controller;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.example.SignatureStatus;
import org.example.domain.beans.JwtParseInfo;
import org.example.domain.dto.LoginDto;
import org.example.domain.dto.TokenDto;
import org.example.domain.model.Result;
import org.example.service.ISysUserService;
import org.example.utils.JwtUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RestController
@RequestMapping("/auth")
public class AuthenticationController {

    private Log logger = LogFactory.getLog(AuthenticationController.class);

    private ISysUserService sysUserService;
    private JwtUtils jwtUtils;

    public AuthenticationController(ISysUserService sysUserService, JwtUtils jwtUtils) {
        this.sysUserService = sysUserService;
        this.jwtUtils = jwtUtils;
    }

    @PostMapping("/token")
    public Result auth(@RequestBody LoginDto loginDto) {
        logger.info(String.format("username: %s, password: %s", loginDto.getUsername(), loginDto.getPassword()));
        return sysUserService.login(loginDto);
    }

    /**
     * 目的：需要带 access_token 以及 refresh_token 来换取新的 access_token
     *     1.access_token 必须是过期状态；如果不是过期状态不允许换取新的token;
     *     2.需要校验 refresh_token, 是正常状态, 就给颁发新的token;
     *     3.如果 refresh_token 也是过期的状态，那么就需要重新登录；如果是被篡改状态，也需要重新登录。
     * @return
     */
    @PostMapping("/refresh/token")
    public Result refreshToken(@RequestBody TokenDto tokenDto, HttpServletRequest request, HttpServletResponse response) {
        String authorization = request.getHeader("Authorization");
        if(StringUtils.hasText(authorization) && authorization.startsWith("Bearer ")) {
            String access_token = authorization.replace("Bearer ", "");
            JwtParseInfo jpi = jwtUtils.validateAccessJwt(access_token);
            switch (jpi.getSignatureStatus()) {
                // 如果是过期状态才允许换新的token
                case expired:
                    // 验证 refresh token
                    jpi = jwtUtils.validateRefreshJwt(tokenDto.getRefreshToken());
                    // refresh token 是正常的状态
                    if(SignatureStatus.correct == jpi.getSignatureStatus()) {
                        // 创建新的 access_token
                        String newAccessToken = jwtUtils.createAccessToken(jpi.getClaims().getSubject());
                        return Result.buildSuccess(newAccessToken);
                    }else {
                        response.setStatus(401);
                        return null;
                    }
                case correct:
                    return Result.buildSuccess(access_token);
                case tamper:
                    response.setStatus(401);
                    return null;
            }
        }else {
            return null;
        }
            response.setStatus(401);
            return null;
        }
}
